package com.lcy.struct.bTreePlus.disk.index;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author lucongyang
 * @date Created in  13:22
 * @description 索引
 */
@Setter
@Getter
@ToString
public class BTreeIndex {
    /**
     * 索引簇
     * eg:单列索引：节点中的关键字[name] 联合索引：节点中的关键字[name, age]
     * 经常用的列优先（最左匹配原则）
     * 离散度高的列优先（离散度高原则）
     * 宽度小的列优先（最少空间原则）
     */
    private List<Comparable> indexList = new ArrayList<>();

    /**
     * 找到在给定索引簇中的位置
     */
    public int findIndex(List<BTreeIndex> indexList) {
        for (int i = 0; i < indexList.size(); i++) {
            if (indexList.get(i).compare(this) > 0) {
                return i;
            }
        }
        return indexList.size();
    }

    /**
     * 比较两个索引簇
     *
     * @return a negative integer, zero, or a positive integer as this object
     * is less than, equal to, or greater than the specified object.
     * @throws RuntimeException 如果索引簇两个类型不一致，长度不一致
     */
    public int compare(BTreeIndex toCompare) {
        if (this.indexList.size() != toCompare.getIndexList().size()) {
            throw new RuntimeException("无法比较索引，长度不一致");
        }
        for (int i = 0; i < this.indexList.size(); i++) {
            if (this.indexList.get(i) instanceof Number && toCompare.indexList.get(i) instanceof Number) {
                int result = new BigDecimal(this.indexList.get(i).toString()).compareTo(
                        new BigDecimal(toCompare.indexList.get(i).toString()));
                if (result != 0) {
                    return result;
                }
            } else if (this.indexList.get(i).getClass().equals(toCompare.indexList.get(i).getClass())) {
                int result = this.indexList.get(i).compareTo(toCompare.indexList.get(i));
                if (result != 0) {
                    return result;
                }
            } else {
                throw new RuntimeException("索引类型不一致无法比较");
            }
        }
        return 0;
    }

    public <T> void addIndex(Comparable<T> comparable) {
        this.indexList.add(comparable);
    }
}
